/**
 * 210524:修正设置extents时没有使用传入参数的错误
 * 210824：升级修改【three.js r120-r131】
 */

let THREE=require('three');
import Collider from './collider';
import CONST from '../collision-const';

/**
 * 盒体
 * @param values {color,extents} color:THREE.Color,extents:[长,宽,高]
 */
export default class BoxCollider extends Collider{
    constructor(values={}){
        super(values);
    }

    //---------------------------------------对外属性及方法----------------------------------------

    /**
     * 获取类型
     * @returns {string}
     */
    get colliderType(){
        return CONST.COLLIDER_TYPE_BOX;
    }

    /**
     * 获取包围盒（世界空间）
     * @returns {Box3}
     */
    get bounds(){
        return this._shape.clone().applyMatrix4(this.matrixWorld);
    }

    /**
     * 获取包围盒（局部空间）
     * @returns {Box3}
     */
    get box(){
        return this._shape.clone();
    }

    /**
     * 获取包围球（局部空间）
     * @returns {Sphere}
     */
    get sphere(){
        return this._sphere.clone();
    }

    /**
     * 获取长宽高
     * @returns {*|null|Vector3}
     */
    get extents(){
        return this._props.extents;
    }

    /**
     * 设置长宽高
     * @param extents {array}
     */
    set extents(extents){
        let e=this._props.extents;
        if(e[0]===extents[0]&&e[1]===extents[1]&&e[2]===extents[2])return;
        /**
         * 210524：增加"=extents[i]"
         */
        let x=this._props.extents[0]=extents[0];
        let y=this._props.extents[1]=extents[1];
        let z=this._props.extents[2]=extents[2];

        this._min.set(-x,-y,-z);
        this._max.set(x,y,z);
        this._shape.min.copy(this._min);
        this._shape.max.copy(this._max);
        this._shape.getBoundingSphere(this._sphere);
    }

    /**
     * 销毁
     */
    dispose(){
        super.dispose();
        this._sphere=null;
        this._min=null;
        this._max=null;
        this._invMat=null;
        this._ray=null;
    }

    //---------------------------------------------------私有属性及方法--------------------------------------------------

    /**
     * 绘制调试
     * @private
     */
    _createDebug(){
        if(this._debug)return;
        this._debug=new THREE.Box3Helper(this._shape,this._props.color);
        this.add(this._debug);
    }

    /**
     * 销毁调试
     * @private
     */
    _destroyDebug(){
        if(!this._debug)return;
        this.remove(this._debug);
        this._debug.geometry.dispose();
        this._debug.material.dispose();
        this._debug=null;
    }

    /**
     * 初始化属性
     * @private
     */
    _initProps(){
        super._initProps();
        this._props.extents=this._values.extents||[0.5,0.5,0.5];
    }

    /**
     * 初始化变量
     * @private
     */
    _initVariable(){
        super._initVariable();
        this._sphere=new THREE.Sphere(new THREE.Vector3(),1);
        this._min=new THREE.Vector3();
        this._max=new THREE.Vector3();
        this._invMat=new THREE.Matrix4();
        this._ray=new THREE.Ray();
    }

    /**
     * 初始化形状
     * @private
     */
    _initShape(){
        let x=this._props.extents[0];
        let y=this._props.extents[1];
        let z=this._props.extents[2];
        this._min.set(-x,-y,-z);
        this._max.set(x,y,z);
        this._shape=new THREE.Box3(this._min,this._max);
        this._shape.getBoundingSphere(this._sphere);
    }

    /**
     * 初始化射线检测函数
     * @private
     */
    _initRaycast() {
        this._raycast=(raycaster,intersects,target)=>{
                let object=this;
                let matrixWorld = this.matrixWorld;
                if ( raycaster.ray.intersectsSphere( this.sphere.applyMatrix4(matrixWorld) ) === false ) return;
                // this._invMat.getInverse( matrixWorld );
                this._invMat.copy( matrixWorld ).invert();
                this._ray.copy( raycaster.ray ).applyMatrix4( this._invMat );
                let intersectPoint=new THREE.Vector3();
                if(this._ray.intersectBox(this._shape,intersectPoint)){
                    intersectPoint.applyMatrix4(matrixWorld);
                    let distance=raycaster.ray.origin.distanceTo(intersectPoint);
                    intersects.push({
                        distance:distance,
                        distanceToRay:0,
                        index: null,
                        face: null,
                        point:intersectPoint,
                        object:target?target:object,
                        shape:object,
                    });
                }
            };
    }
}